<?php

namespace App\Service\CommodityService;

use App\Service\BaseService;
use App\Model\CommodityModel\SupplierCommodity;
use App\Service\HttpServer\Http;
use App\Service\AppService\SystemCacheConfigService;
use Service\AppService\MonitorService;
use App\Model\CommodityModel\SupplierCompany;
use App\Service\Code\Normal;
use App\Model\HmCommodityModel\HmSupplierCommodity;

/**
 * 翻译及图片标准地址转换服务
 * @author chenyun
 */
class HmCommodityGoodsService extends BaseService
{
    /**
     * 附加属性商品详情字段
     * @var
     */
    private $translateArr = [
        'Specifications',
        'VolumeWeight',
        'Skinissues',
        'Skintype',
        'ProductBestUsePeriod',
        'Country',
        'OriginCountry',
        'Manufacturer',
        'Composition',
        'Sleevelength',
        'Toplength',
        'Color',
        'Ingredients'
    ];
    
    /**
     * 指定字段查找数据
     * @param string $supplierCode
     * @param string $field
     * @param int $pageSize
     * @return unknown[]|string[]|array[]
     */
    public function queryCommodityFieldList(string $supplierCode,string $field,int $pageSize = 50)
    {
        $supplier = SupplierCompany::instance()->info(['SupplierCode'=>$supplierCode]);
        if( empty($supplier) ) {
            return Normal::returnCode(Normal::FAIL,"供应商信息不存在!");
        }
        
        $hmCompanyId = $supplier['ID'];
        $lastId = 0;
        while ( true ) 
        {
            $goodsList = HmSupplierCommodity::instance()
            ->select([
                'ID',
                $field,
                'SupplierCommoditySkuCode',
                'SupplierCommoditySpec'
            ])
            ->where('ID','>',$lastId)
            ->where('SupplierCompanyID',$hmCompanyId)
            ->orderBy('ID','ASC')
            ->limit($pageSize)
            ->get()
            ->toArray();
            if( empty($goodsList) ) {
                break;
            }
            
            $endRow = end($goodsList);
            $lastId = $endRow['ID'];
            echo $lastId.PHP_EOL;
            $_fileds_columns = array_column($goodsList,null,$field);
            $_text = array_keys($_fileds_columns);
            $_tmp_text = $this->transferDeepLByHanGuoLanguageToChinese($_text);
            foreach ($goodsList as $goods)
            {
                $_text_key  = md5($goods[$field]);
                $goodsKey   = (string)$goods["SupplierCommoditySkuCode"];//供应商skucode
                $goodsSpecs = $goods["SupplierCommoditySpec"] ? json_decode($goods["SupplierCommoditySpec"],true) : [];//规格
                $goodsSpecs = !empty($goodsSpecs) ? $goodsSpecs : [[]];
                foreach ($goodsSpecs as $spec)
                {
                    //通过原始供应商sku生成新的供应商sku
                    $skuCode = $this->makeMd5SkuCode($hmCompanyId,$goodsKey,$spec);
                    $_result_update = SupplierCommodity::instance()
                    ->where('SupplierCompanyID',$hmCompanyId)
                    ->where('SupplierCommoditySkuCode',$skuCode)
                    ->update([
                        'UpdateTime'    => date("Y-m-d H:i:s"),
                        $field          => $_tmp_text[$_text_key]['output']
                    ]);
                    
                    echo "更新结果:{$skuCode}-{$_result_update}\r\n";
                }
            }
        }
        
        return Normal::returnCode(Normal::SUC,"处理完成");
    }
    
    /**
     * 批量翻译商品主数据接口
     * @param $hmCompanyId
     * @param array $goodsList
     */
    public function queryBatchTranslate($hmCompanyId,array $goodsList)
    {
        //查询是否已经被翻译过的数据，而且必须要要使用原文来组装
        $skuCodes = [];
        foreach ($goodsList as $goodsData) 
        {
            $goodsKey  = (string)$goodsData["SupplierCommoditySkuCode"];//供应商skucode
            $goodsSpecs = $goodsData["SupplierCommoditySpec"] ? json_decode($goodsData["SupplierCommoditySpec"],true) : [];//规格
            $goodsSpecs = !empty($goodsSpecs) ? $goodsSpecs : [[]];
            foreach ($goodsSpecs as $spec)
            {
                //通过原始供应商sku生成新的供应商sku
                $skuCodes[] = $this->makeMd5SkuCode($hmCompanyId,$goodsKey,$spec);
            }
        }
        
        //查询已经被翻译过的SKU
        $hasTranslate = SupplierCommodity::instance()
        ->select([
            'SupplierCommoditySkuCode'
        ])
        ->where('SupplierCompanyID',$hmCompanyId)
        ->whereIn('SupplierCommoditySkuCode',$skuCodes)
        ->where('IsTranslate',1)
        ->get()
        ->toArray();
        
        $hasTranslateMap = array_column($hasTranslate,null,'SupplierCommoditySkuCode');      
        //开始准备翻译的文本
        $deepLText = [];
        foreach ($goodsList as $goodItem)
        {
            $goodsKey  = (string)$goodItem["SupplierCommoditySkuCode"];//供应商skucode
            $goodsSpecs = $goodItem["SupplierCommoditySpec"] ? json_decode($goodItem["SupplierCommoditySpec"],true) : [];//规格            
            $translate_sku  = [];
            if( !empty($goodsSpecs) )
            {
                foreach ($goodsSpecs as $spec)
                {
                    //通过原始供应商sku生成新的供应商sku
                    $skucode = $this->makeMd5SkuCode($hmCompanyId,$goodsKey,$spec);
                    if( empty($hasTranslateMap[$skucode]) ) {
                        //此处追加需要翻译的文本
                        $deepLText[] = $spec['spec_name'];
                        $deepLText[] = $spec['spec_value'];
                        $translate_sku[]  = $skucode;
                    }
                }   
            }
            else 
            {
                //通过原始供应商sku生成新的供应商sku
                $skucode = $this->makeMd5SkuCode($hmCompanyId,$goodsKey);
                $translate_sku[]  = $skucode;
            }
            
            //此处代表当前商品整个无需在翻译
            if( empty($translate_sku) ) {
                continue;
            }
            
            //主商品从未翻译过
            $deepLText[] = $goodItem["SupplierCommodityName"];//商品名
            $deepLText[] = $goodItem["SupplierCommodityBrand"];//品牌
            $deepLText[] = $goodItem["SupplierCommodityClassify"];//分类名
            $deepLText[] = $goodItem["SupplierCommodityOriginPlace"];//产地
            
            //组装商品附加属性
            foreach ($this->translateArr as $field)
            {
                if( !empty($goodItem[$field]) )
                {
                    //主商品从未翻译过
                    $deepLText[] = $goodItem[$field];
                }
            }
        }
        
        if( empty($deepLText) ) {
            return [];
        } 
        
        $min_id = current($goodsList)['ID'];
        //此处需要进行分批翻译，接口
        //Text to be translated. Only UTF-8-encoded plain text is supported. 
        //The parameter may be specified multiple times and translations are returned in the same order as they are requested. 
        //Each of the parameter values may contain multiple sentences.
        //Up to 50 texts can be sent for translation in one request.
        //获取后台翻译配置数量
        $config = SystemCacheConfigService::instance()->getCacheInfoBySystemCode('deepl_config');
        $DeepLTranslateCount = !empty($config['DeepLTranslateCount']) ? $config['DeepLTranslateCount'] : 50;
        
        echo "每次翻译数量:".$DeepLTranslateCount.PHP_EOL;
        echo "总翻译数量:".count($deepLText).PHP_EOL;
        $chunkList = array_chunk($deepLText,$DeepLTranslateCount);
        $deepLData = [];
        foreach ($chunkList as $list) 
        {
            $_tmp_text = $this->transferDeepLByHanGuoLanguageToChinese($list);
            if( empty($_tmp_text) ) {
                echo "翻译停止，当前页ID{$min_id}\r\n";
                exit;
            }
            $deepLData = array_merge($deepLData,$_tmp_text);
        }
        return $deepLData;
    }
    
    /**
     * 处理单个商品翻译
     */
    public function querySingleGoodsTranslate()
    {
        //统一批量翻译
        $deepLText = [
            $goodsName,
            $goodsBrand,
            $className,
            $goodsOriginPlace
        ];
        
        //批量组装规格翻译
        if( !empty($goodsSpec) )
        {
            foreach ($goodsSpec as $item)
            {
                $deepLText[] = $item['spec_name'];
                $deepLText[] = $item['spec_value'];
            }
        }
        
        return $this->transferDeepLByHanGuoLanguageToChinese($deepLText);
    }
    
    /**
     * 处理商品分页报文
     * @param array $imageList
     * @param array $articleList
     * @param string $className
     */
    public function queryPageGoodsList($hmCompanyId,array $goodsList)
    {
        //第一步线获取批量翻译接口数据
        $deepLData = $this->queryBatchTranslate($hmCompanyId,$goodsList);
        $queryGoodsList = [];
        foreach ($goodsList as $goodsData)
        {
            $goodsImgList           = $goodsData["SupplierCommodityImageUrl"];//详情图
            $goodsKey               = (string)$goodsData["SupplierCommoditySkuCode"];//供应商skucode
            $goodsBarCode           = (string)$goodsData["SupplierCommodityInternationBarCode"];//国际条形码
            $goodsName              = $goodsData["SupplierCommodityName"];//商品名
            $goodsBrand             = $goodsData["SupplierCommodityBrand"];//品牌
            $className              = $goodsData["SupplierCommodityClassify"];//分类名
            $goodsPrice             = $goodsData["SupplierCommodityPrice"];//价格
            $stockNumber            = $goodsData["SupplierCommodityStockNumber"];//库存
            $goodsDes               = $goodsData["SupplierCommodityDescription"];//描述
            $taxRate                = $goodsData["TaxRate"];//税率
            $goodsSpec              = $goodsData["SupplierCommoditySpec"] ? json_decode($goodsData["SupplierCommoditySpec"],true) : [];//规格
            $goodsOriginPlace       = $goodsData["SupplierCommodityOriginPlace"];//产地
            $SupplierCommodityType  = $goodsData["SupplierCommodityType"];//类型
            $goodsLink              = $goodsData["SupplierCommodityGoodsLink"];//商品链接
            $Specifications         = $goodsData["Specifications"];//产品规格说明
            $VolumeWeight           = $goodsData["VolumeWeight"];//容积重量
            $Skinissues             = $goodsData["Skinissues"];//产品皮肤问题
            $Skintype               = $goodsData["Skintype"];//适用皮肤类型
            $ProductBestUsePeriod   = $goodsData["ProductBestUsePeriod"];//产品最佳使用期限
            $Country                = $goodsData["Country"];//产地
            $OriginCountry          = $goodsData["OriginCountry"];//原产国
            $Manufacturer           = $goodsData["Manufacturer"];//制造商
            $Composition            = $goodsData["Composition"];//产品构成内容
            $Sleevelength           = $goodsData["Sleevelength"];//商品服装尺寸长度
            $Toplength              = $goodsData["Toplength"];//商品服务顶部长度
            $Color                  = $goodsData["Color"];//颜色
            $Ingredients            = $goodsData["Ingredients"];//商品成分
            
            //统一处理图片为标准地址格式
            $imgList       = $this->checkCommodityImg(json_decode($goodsImgList,true));
            $goodsDes      = $this->checkCommodityImgDes($goodsDes);
            $goodsDes      = $goodsDes ? $goodsDes : $this->imgConvertDes($imgList);
            $goodsImgList  = json_encode($imgList,JSON_UNESCAPED_UNICODE);
            $goodsSpecs    = empty($goodsSpec) ? [[]] : $goodsSpec;
            
            foreach ($goodsSpecs as $spec)
            {
                $SupplierCommodityInfo = [];
                
                //通过原始供应商sku生成新的供应商sku
                $goodsSkuCode = $this->makeMd5SkuCode($hmCompanyId,$goodsKey,$spec);
                
                //判断商品是否已经翻译过
                $SupplierCommodityModel = SupplierCommodity::instance()
                ->where('SupplierCompanyID',$hmCompanyId)
                ->where("SupplierCommoditySkuCode",$goodsSkuCode)
                ->first();
                if($SupplierCommodityModel)
                {
                    $SupplierCommodityInfo = $SupplierCommodityModel->toarray();
                }
                
                if(empty($SupplierCommodityInfo) || $SupplierCommodityInfo["IsTranslate"] == 0)
                {
                    echo "开始写入翻译的数据{$goodsKey}".PHP_EOL;
                    
                    //没有翻译的数据，才能从这里取
                    $ouputGoodsName         = $deepLData[md5($goodsName)]["output"];
                    $ouputGoodsBrand        = $deepLData[md5($goodsBrand)]["output"];
                    $ouputClassName         = $deepLData[md5($className)]["output"];
                    $ouputGoodsOriginPlace  = $deepLData[md5($goodsOriginPlace)]["output"];
                    //获取规格值
                    $specInfo               = $this->getGoodsSpec($spec,$deepLData);
                    //组合商品组
                    $queryGoods = [
                        'goodsImgList'      => $goodsImgList,
                        'goodsName'         => $ouputGoodsName.( empty($specInfo) ? '' : "（属性：".$specInfo[0]["spec_value"]."）"),
                        'goodsNameAlias'    => $goodsName,
                        'goodsBrand'        => $ouputGoodsBrand,
                        'goodsBrandAlias'   => $goodsBrand,
                        'goodsClass'        => $ouputClassName,
                        'goodsClassAlias'   => $className,
                        'goodsPrice'        => $goodsPrice,
                        'goodsSkuCode'      => $goodsSkuCode,
                        'goodsBarCode'      => $goodsBarCode,
                        'stockNumber'       => $stockNumber,
                        'goodsDes'          => $goodsDes,
                        'taxRate'           => $taxRate,
                        'goodsOriginPlace'  => $ouputGoodsOriginPlace,
                        'goodsSpec'         => $specInfo,
                        'commodityType'     => $SupplierCommodityType,
                        'goodsLink'         => $goodsLink,
                        'goodsKey'          => $goodsKey,
                    ];
                    
                    //是否翻译附加属性数据
                    foreach ($this->translateArr as $_field) {
                        $queryGoods[$_field] = !empty($goodsData[$_field]) ? $deepLData[md5($goodsData[$_field])]['output'] : '';
                    }
                }
                else
                {
                    echo "更新旧数据{$goodsSkuCode}\r\n";
                    //组合商品组
                    $queryGoods = [
                        'goodsImgList'      => $goodsImgList,
                        'goodsName'         => $SupplierCommodityInfo["SupplierCommodityName"],
                        'goodsNameAlias'    => $goodsName,
                        'goodsBrand'        => $SupplierCommodityInfo["SupplierCommodityBrand"],
                        'goodsBrandAlias'   => $goodsBrand,
                        'goodsClass'        => $SupplierCommodityInfo["SupplierCommodityClassify"],
                        'goodsClassAlias'   => $className,
                        'goodsPrice'        => $goodsPrice,
                        'goodsSkuCode'      => $goodsSkuCode,
                        'goodsBarCode'      => $goodsBarCode,
                        'stockNumber'       => $stockNumber,
                        'goodsDes'          => $goodsDes,
                        'taxRate'           => $taxRate,
                        'goodsOriginPlace'  => $SupplierCommodityInfo["SupplierCommodityOriginPlace"],
                        'goodsSpec'         => !empty($SupplierCommodityInfo["SupplierCommoditySpec"]) ? json_decode($SupplierCommodityInfo["SupplierCommoditySpec"],true) : [],
                        'commodityType'     => $SupplierCommodityType,
                        'goodsLink'         => $goodsLink,
                        'goodsKey'          => $goodsKey,
                    ];
                    
                    //处理附加属性字段
                    foreach ($this->translateArr as $_field) {
                        $queryGoods[$_field] = !empty($goodsData[$_field]) ? $SupplierCommodityInfo[$_field] : '';
                    }
                }
                
                $queryGoodsList[] = $queryGoods;
            }
        }
        
        return $queryGoodsList;
    }
    
    /**
     * 将图片处理成标准地址格式
     * @param array $imgList
     * @return string[]
     */
    public function checkCommodityImg($imgList)
    {
        if(empty($imgList)){
            return [];
        }
        
        $chList = [];
        foreach ($imgList as $imgurl)
        {
            $img = $this->getImgURL($imgurl);
            if( empty($img) ) {
                continue;
            }
            
            $chList[] = $img;
        }
        return $chList;
    }
    
    /**
     * 将图片处理成标准地址格式 
     * @param unknown $goodsDes
     * @return string
     */
    public function checkCommodityImgDes($goodsDes)
    {
        if(empty($goodsDes)){
            return '';
        }
        
        $imgList = $this->getDesImgArr($goodsDes);
        $ImgDes = '';
        foreach ($imgList as $imgurl)
        {
            $img = $this->getImgURL($imgurl);
            if( empty($img) ) {
                continue;
            }
            
            $ImgDes.= '<p><img src="'.$img.'" style="max-width:100%;" contenteditable="false"/></p>';
        }
        return $ImgDes;
    }
    
    /**
     * 将商品图片处理成详情
     * @param array $imgList
     * @return string
     */
    public function imgConvertDes($imgList)
    {
        if(empty($imgList)){
            return '';
        }
        $ossImgDes  = '';
        foreach ($imgList as $imgurl){
            $ossImgDes.= '<p><img src="'.$imgurl.'" style="max-width:100%;" contenteditable="false"/></p>';
        }
        return $ossImgDes;
    }
    
    /**
     * 有道翻译
     * @param string $language
     */
    public function transferByHanGuoLanguageToChinese(string $language)
    {
        $q = urlencode($language);
        $response = Http::get("https://dict.youdao.com/jsonapi_s?q={$q}&le=ko&t=1&client=web&sign=7b81a6c59623aa7ff423feccee18a041&keyfrom=webdict");
        $result = @json_decode($response,true);
        return $result['fanyi']['tran'] ?? $language;
    }
    
    /**
     * DeepL翻译
     * $url = 'https://api-free.deepl.com/v2/translate';
     * $DeepL_Auth_Key = "23e5ea1c-a076-42d1-aadb-89c9811bcd6f:fx";
     * @param string $language
     */
    public function transferDeepLByHanGuoLanguageToChinese(array $texts)
    {
        $config         = SystemCacheConfigService::instance()->getCacheInfoBySystemCode('deepl_config');
        $url            = $config['URL'];
        $DeepL_Auth_Key = $config['DeepL-Auth-Key'];
        $header = [
            'Content-Type: application/json',
            "Authorization: DeepL-Auth-Key ".$DeepL_Auth_Key
        ];
        $data = [
            'text'          => $texts,
            'target_lang'   => 'ZH',
        ];
        
        echo "开始输入翻译\r\n";
        echo json_encode($data,JSON_UNESCAPED_UNICODE).PHP_EOL;
        $response   = Http::postJsonCurl($url, $data,$header);
        $data       = @json_decode($response,true);
        $translate = [];
        if( !empty($data['translations']) )
        {
            foreach ($texts as $index => $text )
            {
                $translate[md5($text)] =
                [
                    'input'     => $text,
                    'output'    => $data['translations'][$index]['text'] ??'' 
                ];
            }
            
            echo "翻译响应结果\r\n";
            echo json_encode($translate,JSON_UNESCAPED_UNICODE).PHP_EOL;
            return $translate;
        }        
        
               
        //翻译失败的情况下，发送钉钉异常消息，间隔10秒出发一次
        sleep(10);
        $deepLData = [
            'data'      => $data,
            'response'  => $response,
            'url'       => $url,
            'header'    => $header
        ];
        
        $json = json_encode($deepLData,JSON_UNESCAPED_UNICODE);
        echo "翻译失败：{$json}\r\n";
        MonitorService::instance()->sendMsg("DeepL 翻译失败,待翻译报文[{$json}]");
        return $this->transferDeepLByHanGuoLanguageToChinese($texts);
    }
    
    /**
     * 生产新的供应商sku
     * @param unknown $hmCompanyId
     * @param unknown $goodsKey
     * @param array $goodsSpec
     * @return string
     */
    public function makeMd5SkuCode($hmCompanyId,$goodsKey,$goodsSpec= [])
    {
        //新供应商sku生产规则：md5(供应商id+供应商商品原始skucode+对应的规格值),转大写
        //第一步：拼接
        if($goodsSpec){
            $string = $hmCompanyId.$goodsKey.$goodsSpec["spec_value"];
        }else{
            $string = $hmCompanyId.$goodsKey;
        }
        
        //第二步：md5
        $string = md5($string);
        //第三步：转大写
        $string = strtoupper($string);
        return $string;
    }
    
    /**
     * 获取商品规格
     * @param array $goodsSpec
     * @param array $deepLData
     * 建议不要在规格里面进行翻译,如果遇到N个多个规格以上，要调用很多次接口
     */
    public function getGoodsSpec(array $goodsSpec,array $deepLData)
    {
        if( empty($goodsSpec) ) {
            return $goodsSpec;
        }
        $specData[]= [
            "spec_name"         => $deepLData[md5($goodsSpec["spec_name"])]["output"],
            "spec_value"        => $deepLData[md5($goodsSpec["spec_value"])]["output"],
            "spec_name_alias"   => $goodsSpec["spec_name"],
            "spec_value_alias"  => $goodsSpec["spec_value"],
        ];
        return $specData;
    }
    
    /**
     * 获取韩中汇率
     * @return string
     */
    public function getHzRate()
    {
        return '0.005238';
    }
    
    
    /**
     * 组装为标准的图片地址
     * @param string $url
     * @return string
     */
    public function getImgURL(string $url)
    {
        $parse_arr = parse_url($url);
        if( empty($parse_arr['scheme']) ) {
            $scheme = 'https://';
        } else {
            $scheme = $parse_arr['scheme'].'://';
        }
        
        if( !(!empty($parse_arr['host']) && !empty($parse_arr['path'])) ) {
            return '';
        }
        
        return $scheme.$parse_arr['host'].$parse_arr['path'];
    }
    
    /**
     * 提取html模版的图片组
     * @param string $contents
     * @return unknown
     */
    public function getDesImgArr(string $contents)
    {
        preg_match_all('/<img.+?src="(.+?)"[^>]*>/ism', $contents, $matches);
        return !empty($matches[1]) ? $matches[1] : [];
    }
}